package com.example.androidaudiovideodemo.activity

import android.graphics.Color
import android.graphics.ImageFormat
import android.hardware.Camera
import android.os.Handler
import android.os.Looper
import android.os.Message
import android.provider.MediaStore
import android.util.Log
import android.view.SurfaceHolder
import com.blankj.utilcode.util.SDCardUtils
import com.blankj.utilcode.util.TimeUtils
import com.blankj.utilcode.util.ToastUtils
import com.example.androidaudiovideodemo.R
import com.example.androidaudiovideodemo.base.BaseActivity
import com.example.androidaudiovideodemo.utils.AvcEncodeUtil
import kotlinx.android.synthetic.main.activity_mediacodec_h264_camera.*
import kotlinx.android.synthetic.main.activity_mediacodec_h264_camera.task_title_view
import java.io.DataInputStream
import java.io.File
import java.io.FileInputStream
import kotlin.concurrent.thread

/**
 *
 * author: renbing
 *
 * date: 2022/7/1
 *
 * des:
 */
class MediaCodecCameraH264Activity : BaseActivity(){

    private var mCamera: Camera? = null

    private var mIsRecording = false

    private var mWidth = 0
    private var mHeight = 0
    private var mStartTime = 0L
    private var mCount = 0
    private var mEncodeFile: File? = null

    private val mHandler by lazy { object : Handler(Looper.getMainLooper()){
        override fun handleMessage(msg: Message) {
            super.handleMessage(msg)

            if (msg.what == 1){
                mCount++
                val min = mCount/60
                val sec = mCount%60
                val timeStr = "${if (min < 10) 0 else ""}$min:${if (sec < 10) 0 else ""}$sec"
                record_duration_tv.text = timeStr
            }
        }
    } }

    override fun getLayoutId() = R.layout.activity_mediacodec_h264_camera

    override fun performInit() {
        super.performInit()

        setStatusBarColor(this,true)
    }

    override fun initListener() {
        super.initListener()

        task_title_view.run {
            setLeftIconColorFilter(Color.BLACK)
            setOnLeftIconClickListener {
                finish()
            }
        }

        preview_sv.holder.addCallback(object : SurfaceHolder.Callback{
            override fun surfaceCreated(holder: SurfaceHolder) {
                openCamera()
            }

            override fun surfaceChanged(holder: SurfaceHolder,format: Int,width: Int,height: Int) {
            }

            override fun surfaceDestroyed(holder: SurfaceHolder) {
                releaseCamera()
            }

        })

        //录制视频 同时编码
        record_tv.setOnClickListener {
            record_tv.isSelected = !it.isSelected
            if (record_tv.isSelected){
                record_duration_tv.text = "00:00"
                mStartTime = System.currentTimeMillis()
                mIsRecording = true
                mEncodeFile = getOutputFile(MediaStore.Files.FileColumns.MEDIA_TYPE_VIDEO)
                AvcEncodeUtil.initData(mWidth,mHeight,30,mEncodeFile,false)
                mCamera?.setPreviewCallback { data,camera ->
                    AvcEncodeUtil.encodeH264(data) {
                        Log.e("TAG","frame data size:${it.size}")
                    }
                }
                countTime()
            }else{
                mIsRecording = false
                mCamera?.setPreviewCallback { data, camera ->

                }
            }
        }
        //解码
        decode_btn.setOnClickListener {
            if (mEncodeFile == null){
                ToastUtils.showShort("请先录制一段视频再进行解码操作")
                return@setOnClickListener
            }
            if (mIsRecording){
                ToastUtils.showShort("请先结束录制再进行解码操作")
                return@setOnClickListener
            }
            var inputStream: DataInputStream? = null
            try {
                inputStream = DataInputStream(FileInputStream(mEncodeFile))
            }catch (e: Exception){
                e.printStackTrace()
                try {
                    inputStream?.close()
                }catch (e: Exception){
                    e.printStackTrace()
                }
            }
            if (inputStream == null){
                ToastUtils.showShort("源文件转流失败")
                return@setOnClickListener
            }
            AvcEncodeUtil.decodeH264(decode_preview_sv.width,decode_preview_sv.height,decode_preview_sv.holder.surface,inputStream)
        }
    }

    private fun countTime(){
        thread {
            while (mIsRecording){
                Thread.sleep(1000)
                mHandler.sendEmptyMessage(1)
            }
        }
    }

    private fun openCamera(){
        mCamera = Camera.open(Camera.CameraInfo.CAMERA_FACING_BACK)
        val parameters = mCamera?.parameters
        val previewSize = getCameraPreviewSize(parameters)
        mWidth = previewSize?.width?:320
        mHeight = previewSize?.height?:480
        parameters?.run {
            previewFormat = ImageFormat.NV21
            setPreviewSize(mWidth,mHeight)
        }
        mCamera?.setDisplayOrientation(90)
        mCamera?.parameters = parameters
        try {
            mCamera?.setPreviewDisplay(preview_sv.holder)
        }catch (e: Exception){
            e.printStackTrace()
        }
        mCamera?.startPreview()
    }

    private fun getCameraPreviewSize(parameters: Camera.Parameters?): Camera.Size?{
        val previewSizes = parameters?.supportedPreviewSizes
        var needSize: Camera.Size = previewSizes?.get(0) ?:return null
        previewSizes.forEach {
            if (it.width >= needSize.width){
                if (it.height > needSize.height){
                    needSize = it
                }
            }
        }
        return needSize
    }

    private fun getOutputFile(mediaType: Int): File {
        val sdPath = SDCardUtils.getSDCardPathByEnvironment()
        val rootPath = "$sdPath/$packageName/mediacodec"
        val rootFile = File(rootPath)
        if (!rootFile.exists()) {
            rootFile.mkdirs()
        }
        val dir = File(rootFile,if (mediaType == MediaStore.Files.FileColumns.MEDIA_TYPE_IMAGE) "image/encode" else "video/encode")
        if (!dir.exists()) {
            dir.mkdirs()
        }
        val file = File(dir,if (mediaType == MediaStore.Files.FileColumns.MEDIA_TYPE_IMAGE) "IMAGE-${System.currentTimeMillis()}.jpg" else "VIDEO-${System.currentTimeMillis()}.h264")
        if (!file.exists()) {
            file.createNewFile()
        }
        return file
    }

    private fun releaseCamera(){
        mCamera?.run {
            setPreviewCallback(null)
            stopPreview()
            release()
        }
    }
}